#lang racket


(require "../base/base.rkt")
(require "../constructors/main.rkt")

(require "domain.rkt"
         "parametric.rkt")

(provide (struct-out patch)         
         patch-object
         patch-tangent
         patch-normal
         patch-cs)


(define (patch-print patch port mode)
  (write-string "patch(" port)
  (write-string (format "~a" (patch-domain-u patch)) port)
  (write-string " " port)
  (write-string (format "~a" (patch-domain-v patch)) port)
  (write-string ")" port))

(define-struct patch
  (parametric domain-u domain-v)
  #:property prop:custom-write patch-print)


(define (patch-space patch space u-fn v-fn)
  (let ((parametric (patch-parametric patch))
        (u (u-fn (uv-domain-u (patch-domain-u patch))))
        (v (v-fn (uv-domain-v (patch-domain-v patch)))))
    ((space parametric) u v)))

(define (patch-object patch (u-fn (u-fn-min)) (v-fn (v-fn-min)))
  (patch-space patch parametric-object u-fn v-fn))

(define (patch-tangent patch (u-fn (u-fn-min)) (v-fn (v-fn-min)))
  (patch-space patch parametric-tangent u-fn v-fn))

(define (patch-normal patch (u-fn (u-fn-min)) (v-fn (v-fn-min)))
  (patch-space patch parametric-normal u-fn v-fn))

(define (patch-cs patch node (u-fn (u-fn-min)) (v-fn (v-fn-min)))
  (move
   (patch-object patch u-fn v-fn)
   (rotate
    (p<\p uz (patch-normal patch u-fn v-fn))
    (pxp uz (patch-normal patch u-fn v-fn))
    node)))